﻿using Ay.MvcFramework;  
using System;
using System.Collections.Generic;
using System.Collections.ObjectModel;
using System.Diagnostics;
using System.Linq.Expressions;
using System.Windows;
using System.Windows.Input;
using System.Xml.XPath;
using Z.Expressions;


namespace Hotel.UI.Views
{
    //[INotifyPropertyChanged]
    public partial class CalculatorPageViewModel : AyPropertyChanged
    {
        //[ObservableProperty]
        //public string InputText { get => Get<string>(); set => Set(value); }


        //public string CalculatedResult { get => Get<string>(); set => Set(value); }

        private bool isSciOpWaiting = false;
        public ICommand ResetCommand => new DelegateCommand(async (p) =>
        {
            Reset();
        });
        public ICommand CalculateCommand => new DelegateCommand(async (p) =>
        {
            Calculate();
        });
        public ICommand BackspaceCommand => new DelegateCommand(async (p) =>
        {
            Backspace();
        });
        public CalculatorPageViewModel()
        {
            InputText = "Sqrt(100) + (96 - (6 / 3)) + Sin(90)";
        }


        private void Reset()
        {
            CalculatedResult = "0";
            InputText = "";
            isSciOpWaiting = false;
        }


        private async void Calculate()
        {
            if (InputText?.Length == 0)
                return;

            if (isSciOpWaiting)
            {
                InputText += ")";
                isSciOpWaiting = false;
            }

            try
            {

                //Debug.WriteLine(new NCalc.Expression("Sin(0)").Evaluate());
                //string expression = "sin(90)";// "2 + Pow(3, 4) - 2";

                //var evaluator = new CodingSeb.ExpressionEvaluator.ExpressionEvaluator();

                //Console.WriteLine("Result " + evaluator.Evaluate(expression));


                var inputString = NormalizeInputString();
                var expression = new MathExpression(inputString);
                var result3 = expression.Calculate();
                // var expression = new Expression(inputString);
                //var result = expression.Evaluate();
                //var ddd =   CSharpScript.EvaluateAsync<float>("sin(90)").Result;//出错
                //var expression = new org.matheval.Expression("IF(time>8, (HOUR_SALARY*8) + (HOUR_SALARY*1.25*(time-8)), HOUR_SALARY*time)");
                ////bind variable
                //expression.Bind("HOUR_SALARY", 10);
                //expression.Bind("time", 9);
                //var expression = new org.matheval.Expression("SIN(90)");//出错
                //var salary = expression.Eval<float>();
                //Console.WriteLine(salary); //return 92.5
                // var result1 = new DataTable().Compute(inputString, "");
                // var result = float.Parse(result1 + "");
                var result = Eval.Execute<double>(inputString);
                Console.WriteLine(result); // Outputs: 200
               
                //string result2 = new CalcParenthesesExpression().CalculateParenthesesExpression(expression);
                //return float.Parse(result);

                CalculatedResult = result .ToString("G17");
            }
            catch (Exception ex)
            {
                CalculatedResult = "NaN";
            }
        }

        private string NormalizeInputString()
        {
            Dictionary<string, string> _opMapper = new Dictionary<string, string>()
        {
            {"×", "*"},
            {"÷", "/"},
            {"SIN", "Sin"},
            {"COS", "Cos"},
            {"TAN", "Tan"},
            {"ASIN", "Asin"},
            {"ACOS", "Acos"},
            {"ATAN", "Atan"},
            {"LOG", "Log"},
            {"EXP", "Exp"},
            {"LOG10", "Log10"},
            {"POW", "Pow"},
            {"SQRT", "Sqrt"},
            {"ABS", "Abs"},
        };

            var retString = InputText;

            foreach (var key in _opMapper.Keys)
            {
                retString = retString.Replace(key, _opMapper[key]);
            }

            return retString;
        }

        public ICommand NumberInputCommand => new DelegateCommand(async (p) =>
        {
            NumberInput(p as string);
        });


        private void Backspace()
        {
            if (InputText.Length > 0)
                InputText = InputText.Substring(0, InputText.Length - 1);
        }


        private void NumberInput(string key)
        {
            InputText += key;
        }
        public ICommand MathOperatorCommand => new DelegateCommand(async (p) =>
        {
            MathOperator(p as string);
        });

        private void MathOperator(string op)
        {
            if (isSciOpWaiting)
            {
                InputText += ")";
                isSciOpWaiting = false;
            }

            InputText += $" {op} ";
        }
        public ICommand RegionOperatorCommand => new DelegateCommand(async (p) =>
        {
            RegionOperator(p as string);
        });

        private void RegionOperator(string op)
        {
            if (op == ")")
                isSciOpWaiting = false;

            InputText += op;
        }
        public ICommand ScientificOperatorCommand => new DelegateCommand(async (p) =>
        {
            ScientificOperator(p as string);
        });

        private void ScientificOperator(string op)
        {
            InputText += $"{op}(";
            isSciOpWaiting = true;
        }

    }
}
